<template>
  <view class="image-uploader">
    <!-- 上传区域 -->
    <view v-if="!imageUrl" class="upload-area" @click="chooseImage">
      <view class="upload-icon">
        <uni-icons type="camera-filled" size="48" color="#999"></uni-icons>
      </view>
      <text class="upload-text">{{ uploadText }}</text>
      <text class="upload-hint">{{ uploadHint }}</text>
    </view>

    <!-- 图片预览 -->
    <view v-else class="image-preview">
      <image :src="imageUrl" mode="aspectFit" class="preview-image" @click="previewImage"></image>
      <view class="preview-actions">
        <view class="action-btn" @click="handleReupload">
          <uni-icons type="refresh" size="20" color="#1890ff"></uni-icons>
          <text class="btn-text">重新上传</text>
        </view>
        <view class="action-btn" @click="removeImage" v-if="showRemove">
          <uni-icons type="trash" size="20" color="#ff4d4f"></uni-icons>
          <text class="btn-text">删除</text>
        </view>
      </view>
    </view>

    <!-- 加载状态 -->
    <view v-if="loading" class="loading-overlay">
      <view class="loading-content">
        <uni-icons type="spinner-cycle" size="32" color="#1890ff" class="loading-spinner"></uni-icons>
        <text class="loading-text">{{ loadingText }}</text>
      </view>
    </view>

    <!-- 用于图片压缩的隐藏canvas - 修复小程序环境下的绘制问题 -->
    <canvas
      id="compressCanvas"
      canvas-id="compressCanvas"
      style="position: absolute; width: 1200px; height: 1200px; top: -9999px; left: -9999px; z-index: -1; display: block;"
    >
    </canvas>
  </view>
</template>

<script>
import { uploadFile } from '@/utils/upload.js';
import { isHttp } from '@/utils/validate';
import config from '@/config';
// 引入compressorjs进行图片压缩
import Compressor from 'compressorjs';

const baseUrl = config.baseUrl;

export default {
  name: 'ImageUploader',

  props: {
    // 上传提示文字
    uploadText: {
      type: String,
      default: '点击上传图片',
    },
    // 上传提示说明
    uploadHint: {
      type: String,
      default: '请上传清晰的图片',
    },
    // 是否显示删除按钮
    showRemove: {
      type: Boolean,
      default: true,
    },
    // 最大文件大小（MB）
    maxSize: {
      type: Number,
      default: 10,
    },
    // 初始图片URL
    initialImageUrl: {
      type: String,
      default: '',
    },
    // 图片压缩质量 (0-1, 默认0.7)
    compressQuality: {
      type: Number,
      default: 0.5,
      validator: (value) => {
        return value >= 0 && value <= 1;
      },
    },
    // 图片最大宽度（压缩后）
    maxWidth: {
      type: Number,
      default: 1200,
    },
    // 图片最大高度（压缩后）
    maxHeight: {
      type: Number,
      default: 1200,
    },
  },

  data() {
    return {
      imageUrl: '',
      loading: false,
      loadingText: '上传中...',
    };
  },

  watch: {
    initialImageUrl: {
      immediate: true,
      handler(newVal) {
        // 移除不必要的日志
        this.imageUrl = newVal;
      },
    },
  },

  methods: {
    // 选择图片
    chooseImage() {
      // 移除所有调试日志
      console.log('选择图片');
      uni.chooseImage({
        count: 1,
        sizeType: ['original'],
        sourceType: ['album', 'camera'],
        success: (res) => {
          console.log('选择图片成功', res);
          // 简化处理逻辑
          const tempFilePaths = res.tempFilePaths || (res.tempFiles && res.tempFiles.map((file) => file.path)) || [];

          if (!tempFilePaths.length) {
            return;
          }

          const filePath = tempFilePaths[0];

          // 检查文件大小
          uni.getFileInfo({
            filePath: filePath,
            success: (fileInfo) => {
              console.log('文件信息', fileInfo);
              const fileSize = fileInfo.size;
              if (fileSize > this.maxSize * 1024 * 1024) {
                uni.showToast({
                  title: `图片大小不能超过${this.maxSize}MB`,
                  icon: 'none',
                });
                return;
              }

              // 处理并上传图片
              this.processAndUploadImage(filePath);
            },
            fail: () => {
              uni.showToast({
                title: '获取图片信息失败',
                icon: 'none',
              });
            },
          });
        },
        fail: (err) => {
          // 只在用户没有取消时显示错误
          if (!(err.errMsg && err.errMsg.includes('cancel'))) {
            uni.showToast({
              title: '选择图片失败: ' + (err.errMsg || '未知错误'),
              icon: 'none',
            });
          }
        },
      });
    },

    // 处理并上传图片
    processAndUploadImage(filePath) {
      console.log('处理并上传图片', filePath);
      // 显示加载中
      this.loading = true;
      // 压缩图片后再上传
      this.compressImage(filePath)
        .then((compressedPath) => {
          console.log('压缩后的图片路径', compressedPath);
          this.uploadImage(compressedPath);
        })
        .catch((err) => {
          // 压缩失败时使用原图
          this.uploadImage(filePath);
        });
    },

    // 图片压缩方法 - 使用compressorjs实现跨平台图片压缩
    compressImage(filePath) {
      return new Promise((resolve, reject) => {
        console.log('开始压缩图片:', filePath);
        
        // #ifdef MP-WEIXIN
        // 微信小程序环境 - 使用uni-app内置的压缩方法
        try {
          console.log('小程序环境：开始压缩图片');
          // 先获取图片信息
          uni.getImageInfo({
            src: filePath,
            success: (imageInfo) => {
              // 计算压缩后的尺寸
              const maxWidth = this.maxWidth;
              const maxHeight = this.maxHeight;
              let targetWidth = imageInfo.width;
              let targetHeight = imageInfo.height;

              // 等比例缩小图片
              if (targetWidth > maxWidth || targetHeight > maxHeight) {
                const widthRatio = maxWidth / targetWidth;
                const heightRatio = maxHeight / targetHeight;
                const ratio = Math.min(widthRatio, heightRatio);
                targetWidth = Math.floor(targetWidth * ratio);
                targetHeight = Math.floor(targetHeight * ratio);
              }
              
              // 使用微信小程序的图片压缩API
              uni.compressImage({
                src: filePath,
                quality: this.compressQuality * 100, // 微信API要求质量为0-100
                success: (res) => {
                  console.log('小程序压缩成功:', res.tempFilePath);
                  resolve(res.tempFilePath);
                },
                fail: (err) => {
                  console.error('小程序压缩失败:', err);
                  // 失败时使用原图
                  resolve(filePath);
                }
              });
            },
            fail: (err) => {
              console.error('获取图片信息失败:', err);
              resolve(filePath);
            }
          });
        } catch (err) {
          console.error('小程序压缩过程异常:', err);
          resolve(filePath);
        }
        // #endif

        // #ifdef H5
        // H5环境 - 使用compressorjs进行压缩
        try {
          // 判断是否为blob对象或文件对象
          if (filePath instanceof File || filePath instanceof Blob) {
            // 直接使用文件对象
            new Compressor(filePath, {
              quality: this.compressQuality,
              maxWidth: this.maxWidth,
              maxHeight: this.maxHeight,
              success(result) {
                // 转换为DataURL
                const reader = new FileReader();
                reader.readAsDataURL(result);
                reader.onload = function(e) {
                  console.log('H5环境压缩成功 - 使用文件对象');
                  resolve(e.target.result);
                };
                reader.onerror = function() {
                  console.error('文件读取失败');
                  resolve(filePath);
                };
              },
              error(err) {
                console.error('H5环境压缩失败 (文件对象):', err);
                // 失败时使用备用方案
                useFallbackCompression();
              }
            });
          } else if (typeof filePath === 'string') {
            // 对于字符串路径，先加载图片再压缩
            const img = new Image();
            img.crossOrigin = 'anonymous';
            img.onload = function() {
              // 创建canvas
              const canvas = document.createElement('canvas');
              const ctx = canvas.getContext('2d');
              
              // 计算尺寸
              let width = img.width;
              let height = img.height;
              const maxWidth = this.maxWidth;
              const maxHeight = this.maxHeight;
              
              if (width > maxWidth || height > maxHeight) {
                const ratio = Math.min(maxWidth / width, maxHeight / height);
                width = Math.floor(width * ratio);
                height = Math.floor(height * ratio);
              }
              
              // 设置canvas尺寸
              canvas.width = width;
              canvas.height = height;
              
              // 绘制图片
              ctx.fillStyle = '#ffffff';
              ctx.fillRect(0, 0, width, height);
              ctx.drawImage(img, 0, 0, width, height);
              
              // 转换为blob
              canvas.toBlob(function(blob) {
                if (blob) {
                  // 使用compressorjs压缩blob
                  new Compressor(blob, {
                    quality: this.compressQuality,
                    success(result) {
                      const reader = new FileReader();
                      reader.readAsDataURL(result);
                      reader.onload = function(e) {
                        console.log('H5环境压缩成功 - 使用字符串路径');
                        resolve(e.target.result);
                      };
                    },
                    error(err) {
                      console.error('H5环境压缩失败 (字符串路径):', err);
                      useFallbackCompression();
                    }
                  });
                } else {
                  useFallbackCompression();
                }
              }.bind(this), 'image/jpeg', this.compressQuality);
            }.bind(this);
            img.onerror = function() {
              console.error('图片加载失败');
              useFallbackCompression();
            };
            img.src = filePath;
          } else {
            // 类型不支持，使用备用方案
            useFallbackCompression();
          }
          
          // 备用压缩方案
          function useFallbackCompression() {
            console.log('使用备用压缩方案');
            // 创建canvas进行简单压缩
            const img = new Image();
            img.crossOrigin = 'anonymous';
            img.onload = function() {
              const canvas = document.createElement('canvas');
              const ctx = canvas.getContext('2d');
              
              // 计算尺寸
              let width = img.width;
              let height = img.height;
              const maxWidth = this.maxWidth;
              const maxHeight = this.maxHeight;
              
              if (width > maxWidth || height > maxHeight) {
                const ratio = Math.min(maxWidth / width, maxHeight / height);
                width = Math.floor(width * ratio);
                height = Math.floor(height * ratio);
              }
              
              canvas.width = width;
              canvas.height = height;
              
              ctx.fillStyle = '#ffffff';
              ctx.fillRect(0, 0, width, height);
              ctx.drawImage(img, 0, 0, width, height);
              
              // 直接转换为DataURL
              const dataUrl = canvas.toDataURL('image/jpeg', this.compressQuality);
              console.log('备用压缩方案成功');
              resolve(dataUrl);
            }.bind(this);
            img.onerror = function() {
              console.error('备用方案图片加载失败');
              resolve(filePath);
            };
            img.src = typeof filePath === 'string' ? filePath : URL.createObjectURL(filePath);
          }
        } catch (err) {
          console.error('H5压缩过程异常:', err);
          // 备用方案：使用uni-app的canvasToTempFilePath
          try {
            uni.canvasToTempFilePath({
              canvasId: 'compressCanvas',
              fileType: 'jpg',
              quality: this.compressQuality,
              success: (res) => {
                resolve(res.tempFilePath);
              },
              fail: () => {
                resolve(filePath);
              }
            }, this);
          } catch (e) {
            resolve(filePath);
          }
        }
        // #endif
      });
    },

    // 上传图片 - 优化版
    async uploadImage(filePath) {
      this.loading = true;
      this.loadingText = '上传中...';

      try {
        const res = await uploadFile({
          url: '/api/oss/upload',
          filePath: filePath,
          name: 'file',
          formData: {},
        });

        if (res.code === 200) {
          let uploadedUrl = res.url || res.fileName;

          // URL补全逻辑保持不变
          if (!isHttp(uploadedUrl)) {
            uploadedUrl = baseUrl + uploadedUrl;
          }

          this.imageUrl = uploadedUrl;

          // 通知父组件上传完成
          this.$emit('upload-complete', uploadedUrl);

          uni.showToast({
            title: '上传成功',
            icon: 'success',
            duration: 1500, // 稍微缩短显示时间
          });
        } else {
          throw new Error(res.msg || '上传失败');
        }
      } catch (error) {
        // 移除错误日志
        uni.showToast({
          title: error.message || '上传失败',
          icon: 'none',
        });
        this.$emit('upload-error', error);
      } finally {
        this.loading = false;
      }
    },

    // 预览图片
    previewImage() {
      if (this.imageUrl) {
        uni.previewImage({
          urls: [this.imageUrl],
          current: 0,
        });
      }
    },

    // 删除图片
    removeImage() {
      uni.showModal({
        title: '确认删除',
        content: '确定要删除这张图片吗？',
        success: (res) => {
          if (res.confirm) {
            this.imageUrl = '';
            this.$emit('upload-complete', '');
            uni.showToast({
              title: '已删除',
              icon: 'success',
            });
          }
        },
      });
    },

    // 获取当前图片URL
    getImageUrl() {
      return this.imageUrl;
    },

    // 清空图片
    clearImage() {
      this.imageUrl = '';
    },

    // 处理重新上传
    handleReupload() {
      // 直接调用选择图片，移除不必要的日志
      this.chooseImage();
    },
  },
};
</script>

<style scoped>
.image-uploader {
  position: relative;
}

/* 上传区域 */
.upload-area {
  min-height: 200rpx;
  border: 3rpx dashed #c3d4e7;
  border-radius: 16rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #f0f5ff 0%, #ffffff 100%);
  transition: all 0.3s;
  padding: 40rpx;
}

.upload-area:active {
  background: linear-gradient(135deg, #e6f2ff 0%, #f0f8ff 100%);
  border-color: #1890ff;
  transform: scale(0.98);
}

.upload-icon {
  margin-bottom: 20rpx;
}

.upload-text {
  font-size: 28rpx;
  color: #333;
  font-weight: 500;
  margin-bottom: 8rpx;
}

.upload-hint {
  font-size: 24rpx;
  color: #8c9fb3;
}

/* 图片预览 */
.image-preview {
  border-radius: 16rpx;
  overflow: hidden;
  background: #f8f9fa;
  border: 2rpx solid #e9ecef;
}

.preview-image {
  width: 100%;
  height: 300rpx;
  background: #f8f9fa;
}

.preview-actions {
  display: flex;
  justify-content: space-around;
  padding: 20rpx;
  background: #fff;
  border-top: 1rpx solid #e9ecef;
}

.action-btn {
  display: flex;
  align-items: center;
  padding: 12rpx 24rpx;
  border-radius: 20rpx;
  background: #f8f9fa;
  transition: all 0.3s;
}

.action-btn:active {
  background: #e9ecef;
  transform: scale(0.95);
}

.action-btn .btn-text {
  margin-left: 8rpx;
  font-size: 24rpx;
  color: #666;
}

/* 加载状态 */
.loading-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(255, 255, 255, 0.9);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
  border-radius: 16rpx;
}

.loading-content {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.loading-spinner {
  animation: spin 1s linear infinite;
  margin-bottom: 16rpx;
}

.loading-text {
  font-size: 26rpx;
  color: #666;
}

@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
</style>
